package cn.jbt.api.admin.service.impl;

import cn.jbt.api.admin.entity.QSysDictInfo;
import cn.jbt.api.admin.entity.SysDictInfo;
import cn.jbt.api.admin.filter.LoginInfoAccessContext;
import cn.jbt.api.admin.repository.SysDictInfoRepository;
import cn.jbt.api.admin.repository.SysDictOptRepository;
import cn.jbt.api.admin.service.ISysDictInfoService;
import cn.jbt.common.PageQryParam;
import cn.jbt.common.PageQryResult;
import com.querydsl.core.types.ExpressionUtils;
import com.querydsl.core.types.Predicate;
import com.querydsl.jpa.impl.JPAQueryFactory;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Optional;

@Service
@Slf4j
@AllArgsConstructor
public class SysDictInfoServiceImpl implements ISysDictInfoService {

    private final SysDictInfoRepository sysDictInfoRepository;
    private final SysDictOptRepository sysDictOptRepository;
    private final JPAQueryFactory jpaQueryFactory;

    @Override
    public PageQryResult<SysDictInfo> getAllByPage(PageQryParam<SysDictInfo> pageQryParam) {
        SysDictInfo qParam = pageQryParam.getParam();
        QSysDictInfo qSysDictInfo = QSysDictInfo.sysDictInfo;

        Predicate predicate = qSysDictInfo.isNotNull().or(qSysDictInfo.isNull());
        if (null != qParam) {
            if (!StringUtils.isEmpty(qParam.getDictName())) {
                predicate = ExpressionUtils.and(predicate,
                        qSysDictInfo.dictName.contains(qParam.getDictName()));
            }
            if (!StringUtils.isEmpty(qParam.getDictCode())) {
                predicate = ExpressionUtils.and(predicate,
                        qSysDictInfo.dictCode.contains(qParam.getDictCode()));
            }
            if (null != qParam.getStatus()) {
                predicate = ExpressionUtils.and(predicate,
                        qSysDictInfo.status.eq(qParam.getStatus()));
            }
        }

        List<SysDictInfo> list = jpaQueryFactory.select(qSysDictInfo)
                .from(qSysDictInfo)
                .where(predicate)
                .orderBy(qSysDictInfo.id.desc())
                .offset((pageQryParam.getPage() - 1) * pageQryParam.getSize())
                .limit(pageQryParam.getSize())
                .fetch();

        long total = Optional.ofNullable(jpaQueryFactory.select(qSysDictInfo.id.count())
                .from(qSysDictInfo)
                .where(predicate)
                .fetchOne()
        ).orElse(0L);

        return new PageQryResult<>(list, total);
    }

    @Override
    public List<SysDictInfo> getAll(SysDictInfo sysDictInfo) {
        QSysDictInfo qSysDictInfo = QSysDictInfo.sysDictInfo;

        Predicate predicate = qSysDictInfo.isNotNull().or(qSysDictInfo.isNull());
        if (null != sysDictInfo) {
            if (!StringUtils.isEmpty(sysDictInfo.getDictName())) {
                predicate = ExpressionUtils.and(predicate,
                        qSysDictInfo.dictName.contains(sysDictInfo.getDictName()));
            }
            if (!StringUtils.isEmpty(sysDictInfo.getDictCode())) {
                predicate = ExpressionUtils.and(predicate,
                        qSysDictInfo.dictCode.contains(sysDictInfo.getDictCode()));
            }
            if (null != sysDictInfo.getStatus()) {
                predicate = ExpressionUtils.and(predicate,
                        qSysDictInfo.status.eq(sysDictInfo.getStatus()));
            }
        }

        return jpaQueryFactory.select(qSysDictInfo)
                .from(qSysDictInfo)
                .where(predicate)
                .orderBy(qSysDictInfo.id.desc())
                .fetch();
    }

    @Override
    public SysDictInfo add(SysDictInfo sysDictInfo) {
        if (null != sysDictInfoRepository.findFirstByDictCode(sysDictInfo.getDictCode())) {
            throw new RuntimeException("字典编号已存在");
        }

        sysDictInfo.setCreateBy(LoginInfoAccessContext.getLoginInfo().getNickname());
        sysDictInfo.setUpdateBy(sysDictInfo.getCreateBy());
        return sysDictInfoRepository.save(sysDictInfo);
    }

    @Override
    public SysDictInfo edit(SysDictInfo sysDictInfo) {

        SysDictInfo newSysDictInfo = sysDictInfoRepository.findFirstById(sysDictInfo.getId());
        if (null == newSysDictInfo) {
            throw new RuntimeException("404 NotFound");
        }

        if (null != sysDictInfoRepository.findFirstByDictCodeAndIdNot(
                sysDictInfo.getDictCode(), sysDictInfo.getId())) {
            throw new RuntimeException("字典编号已存在");
        }

        newSysDictInfo.edit(sysDictInfo);
        newSysDictInfo.setUpdateBy(LoginInfoAccessContext.getLoginInfo().getNickname());
        return sysDictInfoRepository.save(newSysDictInfo);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void del(List<Long> ids) {
        sysDictInfoRepository.deleteAllByIdInBatch(ids);
        sysDictOptRepository.deleteByDictIdIn(ids);
    }
}
